use serde_json::Value;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::{Mutex, OnceCell};

pub struct AppState {
    structure_map: HashMap<String, Value>,
}

#[derive(Debug)]
pub struct Dbs {
    pub arr_db: Arc<Mutex<HashMap<String, Vec<Value>>>>,
    pub obj_db: Arc<Mutex<HashMap<String, Value>>>,
}
impl Default for Dbs {
    fn default() -> Self {
        Dbs {
            arr_db: Arc::new(Mutex::new(HashMap::new())),
            obj_db: Arc::new(Mutex::new(HashMap::new())),
        }
    }
}

pub static DBS: OnceCell<Dbs> = OnceCell::const_new();

fn build_structure_map(router_map: &HashMap<String, Value>) -> HashMap<String, Value> {
    let mut new_map: HashMap<String, Value> = HashMap::new();
    for (key, value) in router_map {
        match value {
            Value::Array(arr) => {
                if !arr.is_empty() {
                    new_map.insert(key.clone(), arr[0].clone());
                }
            }
            _ => {
                new_map.insert(key.clone(), value.clone());
            }
        }
    }
    new_map
}

pub fn build_db(
    router_map: &HashMap<String, Value>,
) -> (HashMap<String, Vec<Value>>, HashMap<String, Value>) {
    let mut obj_map: HashMap<String, Value> = HashMap::new();
    let mut vec_map: HashMap<String, Vec<Value>> = HashMap::new();
    for (key, value) in router_map {
        match value {
            Value::Array(arr) => {
                vec_map.insert(key.clone(), arr.clone());
            }
            _ => {
                obj_map.insert(key.clone(), value.clone());
            }
        }
    }
    (vec_map, obj_map)
}

impl AppState {
    pub fn new(router_map: HashMap<String, Value>) -> Self {
        let router_map_clone = router_map.clone();
        AppState {
            structure_map: build_structure_map(&router_map_clone),
        }
    }

    pub fn get_structure_map(&self) -> &HashMap<String, Value> {
        &self.structure_map
    }
}
